/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * MainForm.java
 *
 * Created on Jun 29, 2009, 11:50:33 AM
 */

package coda.gui;

import coda.Config;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JList;
import javax.swing.Timer;
import org.bff.javampd.MPD;
import org.bff.javampd.MPDAdmin;
import org.bff.javampd.MPDPlayer;
import org.bff.javampd.MPDPlaylist;
import org.bff.javampd.events.PlayerBasicChangeEvent;
import org.bff.javampd.events.PlayerBasicChangeListener;
import org.bff.javampd.events.PlaylistBasicChangeEvent;
import org.bff.javampd.events.PlaylistBasicChangeListener;
import org.bff.javampd.events.TrackPositionChangeEvent;
import org.bff.javampd.events.TrackPositionChangeListener;
import org.bff.javampd.monitor.MPDStandAloneMonitor;
import org.bff.javampd.objects.MPDSong;

/**
 *
 * @author pan
 */
public class MainForm extends javax.swing.JFrame implements PlayerBasicChangeListener, TrackPositionChangeListener, PlaylistBasicChangeListener, PropertyChangeListener, ActionListener {

    private static MPD mpd = null;
    private MPDStandAloneMonitor monitor;
    private static DefaultListModel model;
    private MPDSong song = null;
    private CollectionPanel collectionPanel = null;
    private PLCPanel plcPanel = null;
    private VolumePanel volumePanel = null;
    private TagPanel tagPanel = null;
    private InfoPanel infoPanel = null;
    private Timer timer = null;

    /** Creates new form MainForm */
    public MainForm() {
        initComponents();
        //
        setIconImage(new ImageIcon(getClass().getResource("/resources/icon.png")).getImage());
        //
        model = (DefaultListModel) list.getModel();
        list.setCellRenderer(new DefaultListCellRenderer(){
            private ImageIcon icon = new ImageIcon(getClass().getResource("/resources/song.png"));
            private ImageIcon none = new ImageIcon(getClass().getResource("/resources/none.png"));
            @Override
            public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                    MPDSong s = (MPDSong) value;
                    if (s != null) {
                        setText(String.format("<html>%d. %s - %s  %d:%02d", index + 1, s.getArtist(), s.getTitle(), s.getLength() / 60, s.getLength() % 60));
                        if (s.equals(song)) { setIcon(icon); } else { setIcon(none); }
                    }
                return this;
            }
        });
        // mpd stuff
        connect();
        refreshSong();
        refreshList();
        attachMonitor();
    }

    private void connect() {
        if (mpd == null) {
            Config conf = Config.getInstance();
            try {
                mpd = new MPD(conf.getProperty("host", "127.0.0.1"), conf.getInteger("port", 6600));
            } catch (Exception e) {
                mpd = null;
                System.err.println(e.getMessage());
            }
        }
    }

    private void disconnect() {
        if (mpd != null) {
            try {
                mpd.close();
            } catch (Exception e) {
                mpd = null;
                System.err.println(e.getMessage());
            }
        }
    }

    private void attachMonitor() {
        if (mpd != null && mpd.isConnected() && monitor == null) {
            monitor = new MPDStandAloneMonitor(mpd);
            monitor.addPlayerChangeListener(this);
            monitor.addTrackPositionChangeListener(this);
            monitor.addPlaylistChangeListener(this);
            monitor.start();
        }
    }

    private void detachMonitor() {
        if (monitor != null) {
            monitor.stop();
            monitor.removePlayerChangeListener(this);
            monitor.removeTrackPositionChangeListener(this);
            monitor.removePlaylistStatusChangedListener(this);
            monitor = null;
        }
    }

    private void refreshList() {
        model.clear();
        try {
            MPDPlaylist playlist = mpd.getMPDPlaylist();
            for (MPDSong s : playlist.getSongList()) {
                model.addElement(s);
            }
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
        list.repaint();
    }

    private void refreshCollection() {
        if (collectionPanel != null) {
            collectionPanel.refresh();
        }
    }

    private void refreshSong() {
        try {
            MPDPlayer player = mpd.getMPDPlayer();
            song = player.getCurrentSong();
            if (song != null) {
                label.setText(String.format("<html><b>%s</b> - %s", song.getArtist(), song.getTitle()));
                progress.setMaximum(song.getLength());
            } else {
                label.setText("");
            }
            //
            if (infoPanel != null) {
                infoPanel.setSong(song);
            }
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
        list.repaint();
    }

    public static void addSong(MPDSong s) {
        MPDPlaylist playlist = mpd.getMPDPlaylist();
        try {
            playlist.addSong(s);
            for (MPDSong so : playlist.getSongList()) {
                if (so.equals(s)) {
                    model.addElement(so);
                    break;
                    //TODO: add not found exception
                }
            }
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }

    public static void deleteSongs(Object[] songs) {
        if (songs.length > 0) {
            MPDPlaylist playlist = mpd.getMPDPlaylist();
            try {
                for (Object s : songs) {
                    playlist.removeSong((MPDSong) s);
                    model.removeElement(s);
                }
            } catch (Exception e) {
                System.err.println(e.getMessage());
            }
            list.repaint();
        }
    }

    public static void deleteSelectedSongs() {
        deleteSongs(list.getSelectedValues());
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        sourceGroup = new javax.swing.ButtonGroup();
        controlPanel = new javax.swing.JPanel();
        previousButton = new javax.swing.JButton();
        playButton = new javax.swing.JToggleButton();
        label = new javax.swing.JLabel();
        stopButton = new javax.swing.JButton();
        progress = new javax.swing.JProgressBar();
        nextButton = new javax.swing.JButton();
        listScrollPanel = new javax.swing.JScrollPane();
        list = new javax.swing.JList();
        menuBar = new javax.swing.JMenuBar();
        fileMenu = new javax.swing.JMenu();
        jSeparator1 = new javax.swing.JSeparator();
        exitMenuItem = new javax.swing.JMenuItem();
        viewMenu = new javax.swing.JMenu();
        collectionMenuItem = new javax.swing.JCheckBoxMenuItem();
        plcMenuItem = new javax.swing.JCheckBoxMenuItem();
        optMenuItem = new javax.swing.JCheckBoxMenuItem();
        tagMenuItem = new javax.swing.JCheckBoxMenuItem();
        infoMenuItem = new javax.swing.JCheckBoxMenuItem();
        refreshMenuItem = new javax.swing.JMenuItem();
        actionsMenu = new javax.swing.JMenu();
        updateMenuItem = new javax.swing.JMenuItem();
        startMenuItem = new javax.swing.JMenuItem();
        stopMenuItem = new javax.swing.JMenuItem();
        helpMenu = new javax.swing.JMenu();
        aboutMenuItem = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Coda");
        getContentPane().setLayout(new java.awt.GridBagLayout());

        controlPanel.setLayout(new java.awt.GridBagLayout());

        previousButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/previous.png"))); // NOI18N
        previousButton.setFocusPainted(false);
        previousButton.setMaximumSize(new java.awt.Dimension(32, 32));
        previousButton.setMinimumSize(new java.awt.Dimension(32, 32));
        previousButton.setPreferredSize(new java.awt.Dimension(32, 32));
        previousButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                previousButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(4, 1, 4, 1);
        controlPanel.add(previousButton, gridBagConstraints);

        playButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/play.png"))); // NOI18N
        playButton.setFocusPainted(false);
        playButton.setMaximumSize(new java.awt.Dimension(36, 36));
        playButton.setMinimumSize(new java.awt.Dimension(36, 36));
        playButton.setPreferredSize(new java.awt.Dimension(36, 36));
        playButton.setPressedIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/pause.png"))); // NOI18N
        playButton.setRolloverIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/play.png"))); // NOI18N
        playButton.setSelectedIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/pause.png"))); // NOI18N
        playButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                playButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(4, 1, 4, 1);
        controlPanel.add(playButton, gridBagConstraints);

        label.setText("Unknown");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 5;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        controlPanel.add(label, gridBagConstraints);

        stopButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/stop.png"))); // NOI18N
        stopButton.setFocusPainted(false);
        stopButton.setMaximumSize(new java.awt.Dimension(32, 32));
        stopButton.setMinimumSize(new java.awt.Dimension(32, 32));
        stopButton.setPreferredSize(new java.awt.Dimension(32, 32));
        stopButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                stopButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 2;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        controlPanel.add(stopButton, gridBagConstraints);

        progress.setMaximumSize(new java.awt.Dimension(32767, 6));
        progress.setMinimumSize(new java.awt.Dimension(10, 6));
        progress.setPreferredSize(new java.awt.Dimension(148, 6));
        progress.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                progressMouseClicked(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 5;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 4, 4);
        controlPanel.add(progress, gridBagConstraints);

        nextButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/next.png"))); // NOI18N
        nextButton.setFocusPainted(false);
        nextButton.setMaximumSize(new java.awt.Dimension(32, 32));
        nextButton.setMinimumSize(new java.awt.Dimension(32, 32));
        nextButton.setPreferredSize(new java.awt.Dimension(32, 32));
        nextButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                nextButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(4, 1, 4, 1);
        controlPanel.add(nextButton, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
        gridBagConstraints.weightx = 0.1;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        getContentPane().add(controlPanel, gridBagConstraints);

        listScrollPanel.setMinimumSize(new java.awt.Dimension(300, 320));
        listScrollPanel.setPreferredSize(new java.awt.Dimension(360, 320));

        list.setModel(new DefaultListModel());
        list.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                listMouseClicked(evt);
            }
        });
        list.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                listKeyPressed(evt);
            }
        });
        listScrollPanel.setViewportView(list);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.1;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
        getContentPane().add(listScrollPanel, gridBagConstraints);

        fileMenu.setText("File");
        fileMenu.add(jSeparator1);

        exitMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_W, java.awt.event.InputEvent.CTRL_MASK));
        exitMenuItem.setText("Exit");
        exitMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                exitMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(exitMenuItem);

        menuBar.add(fileMenu);

        viewMenu.setText("View");

        collectionMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_L, java.awt.event.InputEvent.CTRL_MASK));
        collectionMenuItem.setText("Collection");
        collectionMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                collectionMenuItemActionPerformed(evt);
            }
        });
        viewMenu.add(collectionMenuItem);

        plcMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_P, java.awt.event.InputEvent.CTRL_MASK));
        plcMenuItem.setText("Playlist controls");
        plcMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                plcMenuItemActionPerformed(evt);
            }
        });
        viewMenu.add(plcMenuItem);

        optMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_M, java.awt.event.InputEvent.CTRL_MASK));
        optMenuItem.setText("Volume control");
        optMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                optMenuItemActionPerformed(evt);
            }
        });
        viewMenu.add(optMenuItem);

        tagMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_T, java.awt.event.InputEvent.CTRL_MASK));
        tagMenuItem.setText("Tags");
        tagMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                tagMenuItemActionPerformed(evt);
            }
        });
        viewMenu.add(tagMenuItem);

        infoMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_I, java.awt.event.InputEvent.CTRL_MASK));
        infoMenuItem.setText("Info");
        infoMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                infoMenuItemActionPerformed(evt);
            }
        });
        viewMenu.add(infoMenuItem);

        refreshMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R, java.awt.event.InputEvent.CTRL_MASK));
        refreshMenuItem.setText("Refresh");
        refreshMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                refreshMenuItemActionPerformed(evt);
            }
        });
        viewMenu.add(refreshMenuItem);

        menuBar.add(viewMenu);

        actionsMenu.setText("Actions");

        updateMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_U, java.awt.event.InputEvent.CTRL_MASK));
        updateMenuItem.setText("Update database");
        updateMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                updateMenuItemActionPerformed(evt);
            }
        });
        actionsMenu.add(updateMenuItem);

        startMenuItem.setText("Start MPD");
        startMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                startMenuItemActionPerformed(evt);
            }
        });
        actionsMenu.add(startMenuItem);

        stopMenuItem.setText("Stop MPD");
        stopMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                stopMenuItemActionPerformed(evt);
            }
        });
        actionsMenu.add(stopMenuItem);

        menuBar.add(actionsMenu);

        helpMenu.setText("Help");

        aboutMenuItem.setText("About");
        aboutMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                aboutMenuItemActionPerformed(evt);
            }
        });
        helpMenu.add(aboutMenuItem);

        menuBar.add(helpMenu);

        setJMenuBar(menuBar);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void playButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_playButtonActionPerformed
        try {
            MPDPlayer player = mpd.getMPDPlayer();
            if (playButton.isSelected()) {
                player.play();
            } else {
                player.pause();
            }
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }//GEN-LAST:event_playButtonActionPerformed

    private void listMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_listMouseClicked
        if (evt.getClickCount() == 2) {
            MPDSong s = (MPDSong) list.getSelectedValue();
            if (s != null) {
                try {
                    MPDPlayer player = mpd.getMPDPlayer();
                    player.playId(s);
                } catch (Exception e) {
                    System.err.println(e.getMessage());
                }
            }
        }
    }//GEN-LAST:event_listMouseClicked

    private void stopButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_stopButtonActionPerformed
        try {
            MPDPlayer player = mpd.getMPDPlayer();
            player.stop();
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }//GEN-LAST:event_stopButtonActionPerformed

    private void progressMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_progressMouseClicked
        try {
            int pos = progress.getMaximum() * evt.getX() / progress.getWidth();
            MPDPlayer player = mpd.getMPDPlayer();
            System.out.println("seeking to " + pos);
            player.seek(pos);
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }//GEN-LAST:event_progressMouseClicked

    private void collectionMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_collectionMenuItemActionPerformed
        if (collectionMenuItem.isSelected()) {
            if (collectionPanel == null) {
                collectionPanel = new CollectionPanel(mpd);
                GridBagConstraints c = new GridBagConstraints();
                c.gridx = 3;
                c.gridy = 0;
                c.gridheight = 2;
                c.fill = GridBagConstraints.BOTH;
                c.weightx = 1;
                add(collectionPanel, c);
            }
            // hide info panel
            if (infoPanel != null && infoPanel.isVisible()) {
                infoPanel.setVisible(false);
                infoMenuItem.setSelected(false);
            }
            // show
            collectionPanel.setVisible(true);
        } else {
            collectionPanel.setVisible(false);
        }
        pack();
    }//GEN-LAST:event_collectionMenuItemActionPerformed

    private void listKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_listKeyPressed
        if (evt.getKeyCode() == KeyEvent.VK_DELETE) {
            deleteSongs(list.getSelectedValues());
        }
    }//GEN-LAST:event_listKeyPressed

    private void nextButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextButtonActionPerformed
        MPDPlayer player = mpd.getMPDPlayer();
        try {
            player.playNext();
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }//GEN-LAST:event_nextButtonActionPerformed

    private void previousButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_previousButtonActionPerformed
        MPDPlayer player = mpd.getMPDPlayer();
        try {
            player.playPrev();
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }//GEN-LAST:event_previousButtonActionPerformed

    private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitMenuItemActionPerformed
        System.exit(0);
    }//GEN-LAST:event_exitMenuItemActionPerformed

    private void plcMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_plcMenuItemActionPerformed
        if (plcMenuItem.isSelected()) {
            if (plcPanel == null) {
                plcPanel = new PLCPanel(mpd);
                GridBagConstraints c = new GridBagConstraints();
                c.gridx = 1;
                c.gridy = 1;
                c.fill = GridBagConstraints.BOTH;
                c.weighty = 1;
                add(plcPanel, c);
            }
            plcPanel.setVisible(true);
        } else {
            plcPanel.setVisible(false);
        }
        pack();
    }//GEN-LAST:event_plcMenuItemActionPerformed

    private void optMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_optMenuItemActionPerformed
        if (optMenuItem.isSelected()) {
            if (volumePanel == null) {
                volumePanel = new VolumePanel(mpd);
                GridBagConstraints c = new GridBagConstraints();
                c.gridx = 2;
                c.gridy = 1;
                c.fill = GridBagConstraints.BOTH;
                c.weighty = 1;
                add(volumePanel, c);
            }
            volumePanel.setVisible(true);
        } else {
            volumePanel.setVisible(false);
        }
        pack();
    }//GEN-LAST:event_optMenuItemActionPerformed

    private void aboutMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_aboutMenuItemActionPerformed
        new AboutDialog().setVisible(true);
    }//GEN-LAST:event_aboutMenuItemActionPerformed

    private void updateMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_updateMenuItemActionPerformed
        MPDAdmin adm = mpd.getMPDAdmin();
        try {
            if (timer == null) {
                adm.updateDatabase();
                timer = new Timer(1000, this);
                timer.start();
            } else {
                System.out.println("wait until previous update is finished.");
            }
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }//GEN-LAST:event_updateMenuItemActionPerformed

    private void refreshMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshMenuItemActionPerformed
        refreshList();
    }//GEN-LAST:event_refreshMenuItemActionPerformed

    private void tagMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tagMenuItemActionPerformed
        if (tagMenuItem.isSelected()) {
            MPDSong s = (MPDSong) list.getSelectedValue();
            //
            if (tagPanel == null) {
                tagPanel = new TagPanel(list);
                GridBagConstraints c = new GridBagConstraints();
                c.gridx = 5;
                c.gridy = 0;
                c.fill = GridBagConstraints.BOTH;
                c.weighty = 1;
                c.gridheight = 2;
                add(tagPanel, c);
            }
            tagPanel.setSong(s);
            tagPanel.setVisible(true);
        } else {
            tagPanel.setVisible(false);
        }
        pack();
    }//GEN-LAST:event_tagMenuItemActionPerformed

    private void infoMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_infoMenuItemActionPerformed
        if (infoMenuItem.isSelected()) {
            MPDSong s = (MPDSong) list.getSelectedValue();
            //
            if (infoPanel == null) {
                infoPanel = new InfoPanel();
                GridBagConstraints c = new GridBagConstraints();
                c.gridx = 3;
                c.gridy = 0;
                c.fill = GridBagConstraints.BOTH;
                c.weightx = 1;
                c.weighty = 1;
                c.gridheight = 2;
                add(infoPanel, c);
            }
            // hide collection panel
            if (collectionPanel != null && collectionPanel.isVisible()) {
                collectionPanel.setVisible(false);
                collectionMenuItem.setSelected(false);
            }
            // show
            infoPanel.setVisible(true);
            infoPanel.setSong(song);
            label.setVisible(false);
        } else {
            infoPanel.setVisible(false);
            label.setVisible(true);
        }
        pack();
    }//GEN-LAST:event_infoMenuItemActionPerformed

    private void startMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_startMenuItemActionPerformed
        try {
            Process process = Runtime.getRuntime().exec("mpd");
            int result = process.waitFor();
            if (result == 0) {
                connect();
                attachMonitor();
            }
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }//GEN-LAST:event_startMenuItemActionPerformed

    private void stopMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_stopMenuItemActionPerformed
        try {
            //detachMonitor();
            MPDAdmin admin = mpd.getMPDAdmin();
            admin.killMPD();
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }//GEN-LAST:event_stopMenuItemActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuItem aboutMenuItem;
    private javax.swing.JMenu actionsMenu;
    private javax.swing.JCheckBoxMenuItem collectionMenuItem;
    private javax.swing.JPanel controlPanel;
    private javax.swing.JMenuItem exitMenuItem;
    private javax.swing.JMenu fileMenu;
    private javax.swing.JMenu helpMenu;
    private javax.swing.JCheckBoxMenuItem infoMenuItem;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JLabel label;
    private static javax.swing.JList list;
    private javax.swing.JScrollPane listScrollPanel;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JButton nextButton;
    private javax.swing.JCheckBoxMenuItem optMenuItem;
    private javax.swing.JToggleButton playButton;
    private javax.swing.JCheckBoxMenuItem plcMenuItem;
    private javax.swing.JButton previousButton;
    private javax.swing.JProgressBar progress;
    private javax.swing.JMenuItem refreshMenuItem;
    private javax.swing.ButtonGroup sourceGroup;
    private javax.swing.JMenuItem startMenuItem;
    private javax.swing.JButton stopButton;
    private javax.swing.JMenuItem stopMenuItem;
    private javax.swing.JCheckBoxMenuItem tagMenuItem;
    private javax.swing.JMenuItem updateMenuItem;
    private javax.swing.JMenu viewMenu;
    // End of variables declaration//GEN-END:variables

    public void playerBasicChange(PlayerBasicChangeEvent event) {
        String message;
        switch (event.getId()) {
            case (PlayerBasicChangeEvent.PLAYER_STARTED) :
            case (PlayerBasicChangeEvent.PLAYER_UNPAUSED) :
                playButton.setSelected(true);
                message = "player: playing";
                break;
            case (PlayerBasicChangeEvent.PLAYER_STOPPED) :
            case (PlayerBasicChangeEvent.PLAYER_PAUSED) :
                playButton.setSelected(false);
                message = "player: stopped/paused";
                break;
            case (PlayerBasicChangeEvent.PLAYER_BITRATE_CHANGE) :
                message = "bitrate change";
                break;
            default: message = "unknown";
        }
        System.out.println(message);
    }

    public void trackPositionChanged(TrackPositionChangeEvent event) {
        progress.setValue((int) event.getElapsedTime());
    }

    public void playlistBasicChange(PlaylistBasicChangeEvent event) {
        String message;
        switch (event.getId()) {
            case (PlaylistBasicChangeEvent.SONG_CHANGED) :
                refreshSong();
                message = "song changed";
                break;
            case (PlaylistBasicChangeEvent.SONG_ADDED) :
                message = "song added";
                break;
            case (PlaylistBasicChangeEvent.SONG_DELETED) :
                message = "song deleted";
                break;
            case (PlaylistBasicChangeEvent.PLAYLIST_CHANGED) :
                message = "playlist changed";
                break;
            case (PlaylistBasicChangeEvent.PLAYLIST_ENDED) :
                refreshSong();
                message = "playlist ended";
                break;
            default :
                message = "";
        }
        System.out.println(message);
    }

    public void propertyChange(PropertyChangeEvent event) {
        if (event.getPropertyName().equals("rred")) {
            System.out.println("position: " + event.getNewValue());
        } else {
            System.out.println("event: " + event);
        }
    }

    /**
     * Event generated by timer
     * @param event
     */
    public void actionPerformed(ActionEvent event) {
        System.out.println("checking db update status...");
        try {
            boolean finished = true;
            for (String status : mpd.getStatus()) {
                if (status.startsWith("updating_db")) {
                    finished = false;
                    break;
                }
            }
            if (finished) {
                System.out.println("done.");
                timer.stop();
                timer = null;
                //
                refreshList();
                refreshCollection();
            } else {
                System.out.println("still updating...");
            }
        } catch (Exception e) {
            System.err.println(e.getMessage());
            timer.stop();
            timer = null;
        }
    }

}
